﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using GraphDrawer.GraphProvider;
using Microsoft.VirtualEarth.MapControl;

namespace GraphDrawer.SocialNetworks
{
    public partial class SocialNetworkViewer : UserControl
    {
        string socialNetwork;
        Graph m_graph;
        GraphLayout.GraphRepresentation.Graph gg;
        GraphProvider.GraphProviderServiceSoapClient cl;
        public Dictionary<GraphElement, GraphLayout.Interface.VisualItem> map = new Dictionary<GraphElement, GraphLayout.Interface.VisualItem>();

        public SocialNetworkViewer(String socialNetworkName)
        {
            InitializeComponent();

            cl = new GraphProviderServiceSoapClient();
            cl.netToGraphmlCompleted += new EventHandler<netToGraphmlCompletedEventArgs>(cl_netToGraphmlCompleted);
            cl.GetGraphFromGraphMLCompleted += new EventHandler<GetGraphFromGraphMLCompletedEventArgs>(cl_GetGraphFromGraphMLCompleted);
            LayoutRoot.SizeChanged += new SizeChangedEventHandler(LayoutRoot_SizeChanged);
            OldElements += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(VirtualEarthControl_OldElements);
            NewEdges += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(VirtualEarthControl_NewEdges);

            cl.netToGraphmlAsync(socialNetworkName);
        }

        void cl_GetGraphFromGraphMLCompleted(object sender, GetGraphFromGraphMLCompletedEventArgs e)
        {
            m_graph = e.Result;

            gg = new GraphLayout.GraphRepresentation.Graph();
            gg.NewEdges += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(gg_NewEdges);
            gg.OldElements += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(gg_OldElements);
            gg.Nodes = new System.Collections.ObjectModel.ObservableCollection<GraphLayout.Interface.VisualItem>();
            gg.Edges = new System.Collections.ObjectModel.ObservableCollection<GraphLayout.GraphRepresentation.EdgeItem>();

            foreach (var item in m_graph.Vertices)
            {
                double? latitude = null;
                double? longitude = null;
                bool noPushpin = false;
                foreach (var key in item.Keys)
                {
                    if (key.Key == "locationX")
                    {
                        latitude = Convert.ToDouble(key.Value, System.Globalization.NumberFormatInfo.InvariantInfo);
                    }
                    if (key.Key == "locationY")
                    {
                        longitude = Convert.ToDouble(key.Value, System.Globalization.NumberFormatInfo.InvariantInfo);
                    }

                    if (latitude.HasValue && longitude.HasValue && !noPushpin)
                    {
                        AddPushpin(latitude.Value, longitude.Value, item);
                        noPushpin = true;
                    }

                }
                if (!latitude.HasValue && !longitude.HasValue)
                {
                    foreach (var key in item.Keys)
                    {
                        if (key.Key == "location")
                        {
                            cl.GetGeoCodeAsync(key.Value, item);
                            break;
                        }
                    }
                }


            }

            /*if (simulationPage.map.Count < m_graph.Vertices.Count)
                return;

            foreach (var item in m_graph.Edges)
            {
                var n1 = (from v in m_graph.Vertices
                          where v.Id == item.Source
                          select v).First();
                var n2 = (from v in m_graph.Vertices
                          where v.Id == item.Target
                          select v).First();

                GraphLayout.GraphRepresentation.EdgeItem e1 = new GraphLayout.GraphRepresentation.EdgeItem();
                e1.Target = simulationPage.map[n2];
                e1.Source = simulationPage.map[n1];
                e1.Graph = gg;

                //gg.Edges.Add(e1);

                var line = prefuse.action.layout.Layout.DrawLine(
                        (e1.Source.Element as GraphElement).x,
                        (e1.Source.Element as GraphElement).y,
                        (e1.Target.Element as GraphElement).x,
                        (e1.Target.Element as GraphElement).y);


                e1.VisualLine = line;
                e1.Children.Add(line);

                //e1.SetValue(MapLayer.MapPositionProperty, new Microsoft.VirtualEarth.MapControl.Location(line.X1, line.Y1));
                /*e1.SetValue(MapLayer.MapPositionProperty, new Microsoft.VirtualEarth.MapControl.MapPolyline() {
                    Locations = new LocationCollection() {
                        new Location(line.X1, line.Y1),
                        new Location(line.X2, line.Y2)
                    }
                });*//*
                e1.SetValue(MapLayer.MapPositionMethodProperty, PositionMethod.Center);

                e1.SetValue(Canvas.ZIndexProperty, -10);

                //(Map.FindName("PushpinLayer") as MapLayer).AddChild(e1);
                (Map.FindName("PushpinLayer") as MapLayer).AddChild(
                    new Microsoft.VirtualEarth.MapControl.MapPolyline()
                    {
                        Locations = new LocationCollection() {
							new Location(line.X1, line.Y1),
							new Location(line.X2, line.Y2)
						},
                        Stroke = new SolidColorBrush(Color.FromArgb(255, 0, 255, 255)),
                        StrokeThickness = 1.0,
                    }
                );
            }*/
        }

        void cl_netToGraphmlCompleted(object sender, netToGraphmlCompletedEventArgs e)
        {
            socialNetwork = e.Result;
            cl.GetGraphFromGraphMLAsync(socialNetwork);
        }

        void LayoutRoot_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Map.Width = e.NewSize.Width;
            Map.Height = e.NewSize.Height;
        }
        
        void nodeCanvas_NodeSelected(object sender, MouseEventArgs e)
        {
            var curr = sender as GraphLayout.GraphRepresentation.NodeItem;
            var prev = curr.Graph.PreviousSelectedNode as GraphLayout.GraphRepresentation.NodeItem;

            if (prev != null)
            {
                GraphElement n = prev.Element as GraphElement;

                String text = String.Empty;
                foreach (var description in n.Keys)
                {
                    if (description.Key == "stateName")
                    {
                        text = description.Value;
                        break;
                    }
                }

                ((Ellipse)prev.Children[0]).Fill = new SolidColorBrush(Colors.Transparent);//simulationPage.GetColorForDisease(text);
                ((Ellipse)prev.Children[0]).Stroke = new SolidColorBrush(Color.FromArgb(255, 50, 50, 50));
                ((Ellipse)prev.Children[0]).StrokeThickness = 1.0;
            }
            if (curr != null)
            {
                GraphElement n = curr.Element as GraphElement;

                var ditails = (Map.FindName("ditails") as PatientDetails);
                ditails.UpdateDetails(n.Keys);



                ((Ellipse)curr.Children[0]).Fill = new SolidColorBrush(Color.FromArgb(128, 55, 55, 100));
                ((Ellipse)curr.Children[0]).Stroke = new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
                ((Ellipse)curr.Children[0]).StrokeThickness = 2.0;
            }
        }

        private void AddPushpin(double latitude, double longitude, GraphElement elem)
        {
            var node = (GraphLayout.GraphRepresentation.NodeItem)GleeGraphDrawer.CreateNodeCanvas(elem, null);

            gg.Nodes.Add(node);
            ((GraphLayout.GraphRepresentation.NodeItem)gg.Nodes.Last()).Graph = gg;
            gg.Nodes.Last().Element = elem;
            elem.x = latitude;
            elem.y = longitude;

            ((GraphLayout.GraphRepresentation.NodeItem)gg.Nodes.Last()).MouseEnter += new MouseEventHandler(GleeGraphDrawer.SetInfoPanel);
            ((GraphLayout.GraphRepresentation.NodeItem)gg.Nodes.Last()).MouseLeave += new MouseEventHandler(GleeGraphDrawer.ResetInfoPanel);
            ((GraphLayout.GraphRepresentation.NodeItem)gg.Nodes.Last()).NodeSelected += new MouseEventHandler(nodeCanvas_NodeSelected);

            node.SetValue(MapLayer.MapPositionProperty, new Microsoft.VirtualEarth.MapControl.Location(latitude, longitude));
            node.SetValue(MapLayer.MapPositionMethodProperty, PositionMethod.Center);

            //simulationPage.map.Add(elem, node);
            map.Add(elem, node);

            (Map.FindName("PushpinLayer") as MapLayer).AddChild(node);
        }

        void gg_NewEdges(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {

        }

        void gg_OldElements(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {

        }

        void VirtualEarthControl_NewEdges(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    foreach (GraphLayout.GraphRepresentation.EdgeItem item in e.NewItems)
                    {
                        var line = prefuse.action.layout.Layout.DrawLine(item.Source.X + ((GraphLayout.GraphRepresentation.NodeItem)item.Source).Width / 2,
                                item.Source.Y + ((GraphLayout.GraphRepresentation.NodeItem)item.Source).Height / 2,
                                item.Target.X + ((GraphLayout.GraphRepresentation.NodeItem)item.Target).Width / 2,
                                item.Target.Y + ((GraphLayout.GraphRepresentation.NodeItem)item.Target).Height / 2);

                        item.VisualLine = line;
                        item.Children.Add(line);


                        item.SetValue(MapLayer.MapPositionProperty, new Microsoft.VirtualEarth.MapControl.Location(line.X1, line.Y1));
                        item.SetValue(MapLayer.MapPositionMethodProperty, PositionMethod.Center);

                        //item.SetValue(Canvas.ZIndexProperty, -10);
                        //this.Children.Add(item);
                    }
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    foreach (GraphLayout.GraphRepresentation.EdgeItem item in e.OldItems)
                    {
                        (Map.FindName("PushpinLayer") as MapLayer).RemoveChild(item);
                    }
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    break;
                default:
                    break;
            }
        }

        void VirtualEarthControl_OldElements(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {

        }


        #region IGraph Members

        public event System.Collections.Specialized.NotifyCollectionChangedEventHandler NewEdges;

        public event System.Collections.Specialized.NotifyCollectionChangedEventHandler OldElements;

        public System.Collections.ObjectModel.ObservableCollection<GraphLayout.Interface.VisualItem> Nodes
        {
            get
            {
                return gg.Nodes;
            }
        }

        public System.Collections.ObjectModel.ObservableCollection<GraphLayout.GraphRepresentation.EdgeItem> Edges
        {
            get
            {
                return gg.Edges;
            }
        }

        public GraphLayout.Interface.VisualItem SelectedNode
        {
            get
            {
                //throw new NotImplementedException();
                return gg.Nodes[1];
            }
            set
            {
                //throw new NotImplementedException();
            }
        }

        public GraphLayout.Interface.VisualItem PreviousSelectedNode
        {
            get
            {
                //throw new NotImplementedException();
                return gg.Nodes[0];
            }
            set
            {
                //throw new NotImplementedException();
            }
        }

        #endregion
    }
}
